/*
    SUSAN® - Sole of Unix Save ANything

   Copyright (C) 2020-2020 Hechzh Property

   

   

   
*/

/* Load the python-fd plugin and test it */

#if defined(HAVE_MINGW)
#include "include/susan.h"
#endif

#include "Python.h"
#include "plugins/include/capsulethunk.h"
#include "plugins/include/python3compat.h"
class PoolMem;
#define NbytesForBits(n) ((((n)-1) >> 3) + 1)
typedef off_t boffset_t;

#include "lib/plugins.h"
#include "filed/fd_plugins.h"
#include "../module/susanfd.h"
static void PyErrorHandler()
{
  PyObject *type, *value, *traceback;
  PyObject* tracebackModule;
  char* error_string;

  PyErr_Fetch(&type, &value, &traceback);
  PyErr_NormalizeException(&type, &value, &traceback);

  tracebackModule = PyImport_ImportModule("traceback");
  if (tracebackModule != NULL) {
    PyObject *tbList, *emptyString, *strRetval;

    tbList =
        PyObject_CallMethod(tracebackModule, (char*)"format_exception",
                            (char*)"OOO", type, value == NULL ? Py_None : value,
                            traceback == NULL ? Py_None : traceback);

    emptyString = PyUnicode_FromString("");
    strRetval =
        PyObject_CallMethod(emptyString, (char*)"join", (char*)"O", tbList);

    error_string = strdup(PyUnicode_AsUTF8(strRetval));

    Py_DECREF(tbList);
    Py_DECREF(emptyString);
    Py_DECREF(strRetval);
    Py_DECREF(tracebackModule);
  } else {
    error_string = strdup("Unable to import traceback module.");
  }
  Py_DECREF(type);
  Py_XDECREF(value);
  Py_XDECREF(traceback);
  printf("%s", error_string);

  free(error_string);
  exit(1);
}

using namespace filedaemon;
bRC susanRegisterEvents(PluginContext* ctx, int nr_events, ...)
{
  return bRC_OK;
};
bRC susanUnRegisterEvents(PluginContext* ctx, int nr_events, ...)
{
  return bRC_OK;
};
bRC susanGetInstanceCount(PluginContext* ctx, int* ret) { return bRC_OK; };
bRC susanGetValue(PluginContext* ctx, filedaemon::bVariable var, void* value)
{
  return bRC_OK;
};
bRC susanSetValue(PluginContext* ctx, filedaemon::bVariable var, void* value)
{
  return bRC_OK;
};
bRC susanJobMsg(PluginContext* ctx,
                 const char* file,
                 int line,
                 int type,
                 utime_t mtime,
                 const char* fmt,
                 ...)
{
  printf("susanJobMsg file:%s line:%d type:%d time: %ld, fmt:%s\n", file, line,
         type, (int64_t)mtime, fmt);
  return bRC_OK;
};
bRC susanDebugMsg(PluginContext* ctx,
                   const char* file,
                   int line,
                   int level,
                   const char* fmt,
                   ...)
{
  printf("susanDebugMsg file:%s line:%d level:%d fmt:%s\n", file, line, level,
         fmt);
  return bRC_OK;
};
void* susanMalloc(PluginContext* ctx, const char* file, int line, size_t size)
{
  return NULL;
};
void susanFree(PluginContext* ctx, const char* file, int line, void* mem)
{
  return;
};
bRC susanAddExclude(PluginContext* ctx, const char* file) { return bRC_OK; };
bRC susanAddInclude(PluginContext* ctx, const char* file) { return bRC_OK; };
bRC susanAddOptions(PluginContext* ctx, const char* opts) { return bRC_OK; };
bRC susanAddRegex(PluginContext* ctx, const char* item, int type)
{
  return bRC_OK;
};
bRC susanAddWild(PluginContext* ctx, const char* item, int type)
{
  return bRC_OK;
};
bRC susanNewOptions(PluginContext* ctx) { return bRC_OK; };
bRC susanNewInclude(PluginContext* ctx) { return bRC_OK; };
bRC susanNewPreInclude(PluginContext* ctx) { return bRC_OK; };
bRC susanCheckChanges(PluginContext* ctx, struct filedaemon::save_pkt* sp)
{
  return bRC_OK;
};
bRC susanAcceptFile(PluginContext* ctx, struct filedaemon::save_pkt* sp)
{
  return bRC_OK;
}; /* Need fname and statp */
bRC susanSetSeenBitmap(PluginContext* ctx, bool all, char* fname)
{
  return bRC_OK;
};
bRC susanClearSeenBitmap(PluginContext* ctx, bool all, char* fname)
{
  return bRC_OK;
};


/* Susan entry points */
static filedaemon::CoreFunctions susan_core_functions = {
    sizeof(filedaemon::CoreFunctions),
    FD_PLUGIN_INTERFACE_VERSION,
    susanRegisterEvents,
    susanUnRegisterEvents,
    susanGetInstanceCount,
    susanGetValue,
    susanSetValue,
    susanJobMsg,
    susanDebugMsg,
    susanMalloc,
    susanFree,
    susanAddExclude,
    susanAddInclude,
    susanAddOptions,
    susanAddRegex,
    susanAddWild,
    susanNewOptions,
    susanNewInclude,
    susanNewPreInclude,
    susanCheckChanges,
    susanAcceptFile,
    susanSetSeenBitmap,
    susanClearSeenBitmap};


// create plugin context

Plugin plugin = {(char*)"python-fd-module-teste", 123, NULL, NULL, NULL};

static PluginContext susan_PluginContext = {0, &plugin, NULL, NULL};

int main(int argc, char* argv[])
{
  /* Py_SetProgramName(argv[0]); */
  Py_Initialize();

  PyObject* susanfdModule = PyImport_ImportModule("susanfd");
  if (susanfdModule) {
    printf("loaded susanfd successfully\n");
  } else {
    printf("loading of susanfd failed\n");
  }
  if (PyErr_Occurred()) { PyErrorHandler(); }

  import_susanfd();
  Susanfd_set_susan_core_functions(&susan_core_functions);
  Susanfd_set_plugin_context(&susan_PluginContext);

  PyObject* pModule = PyImport_ImportModule("susanfd-module-test");

  if (PyErr_Occurred()) { PyErrorHandler(); }
  PyObject* pDict = PyModule_GetDict(pModule);
  PyObject* pFunc = PyDict_GetItemString(pDict, "load_susan_plugin");

  if (pFunc && PyCallable_Check(pFunc)) {
    printf("load_susan_plugin found and is callable\n");
    PyObject *pPluginDefinition, *pRetVal;


    pPluginDefinition = PyUnicode_FromString((char*)"PluginDefinition");

    pRetVal = PyObject_CallFunctionObjArgs(pFunc, pPluginDefinition, NULL);

    Py_DECREF(pPluginDefinition);
    if (pRetVal) { Py_DECREF(pRetVal); }
    if (PyErr_Occurred()) { PyErrorHandler(); }
  } else {
    printf("load_susan_plugin() not found in module");
  }
  Py_DECREF(pDict);
  Py_DECREF(pFunc);

  Py_DECREF(pModule);
  Py_Finalize();
  return 0;
}
